package com.niuwa.p2p.interceptor;

import java.io.Serializable;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

/**
 * @ClassName: MethodCacheInterceptor
 * @Description: 载入缓存
 * @author: zhangbo
 * @date:2015年1月13日 下午2:41:17
 */
public class MethodCacheInterceptor implements MethodInterceptor,
		InitializingBean {

	private static Logger logger = Logger
			.getLogger(MethodCacheInterceptor.class);

	@Autowired
	private Cache cache;

	@Value("#{propertiesReader['system.devMode']}")
	private boolean isDevMode;

	@Override
	public void afterPropertiesSet() throws Exception {
		if (null == cache)
			throw new IllegalArgumentException("Cache should not be null.");
	}

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		if (!isDevMode) {
			String targetName = invocation.getThis().getClass().getName();
			String methodName = invocation.getMethod().getName();
			Object[] arguments = invocation.getArguments(); // 调用的参数
			String cacheKey = this.getCacheKey(targetName, methodName,
					arguments);
			Element element = cache.get(cacheKey);
			Object result = null;
			if (null == element) {
				logger.info("Cache start.");
				result = getResultByMethodInvocation(invocation);
				element = new Element(cacheKey, (Serializable) result); // 缓存执行结果
				cache.put(element);
			}
			logger.info(element.getObjectKey());
			return element.getObjectValue();
		} else {
			return invocation.proceed();
		}
	}

	/**
	 * @param invocation
	 * @return Object
	 * @throws Throwable
	 */
	private Object getResultByMethodInvocation(MethodInvocation invocation)
			throws Throwable {
		return invocation.proceed();
	}

	/**
	 * @param targetName
	 * @param methodName
	 * @param arguments
	 * @return String
	 */
	private String getCacheKey(String targetName, String methodName,
			Object[] arguments) {
		StringBuffer sb = new StringBuffer();
		sb.append(targetName).append(".").append(methodName);
		if (null != arguments && arguments.length != 0) {
			for (int index = 0; index < arguments.length; index++) {
				sb.append(".").append(arguments[index]);
			}
		}
		return sb.toString();
	}

}
